/**
 * Pod 自动伸缩
 * Created by dell2 on 2017/2/6.
 * refer to the k8s auto scaling function offer pod auto scale interface
 * details see k8s api:  https://kubernetes.io/docs/api-reference/autoscaling/v1/operations/
 *
 * response example:
 * {
	"kind" : "HorizontalPodAutoscaler",
	"apiVersion" : "autoscaling/v1",
	"metadata" : {
		"name" : "scale-test",
		"namespace" : "fanjun",
		"selfLink" : "/apis/autoscaling/v1/namespaces/fanjun/horizontalpodautoscalers/scale-test",
		"uid" : "111d3c87-ed05-11e6-a484-00163e04582e",
		"resourceVersion" : "13139080",
		"creationTimestamp" : "2017-02-07T07:14:29Z"
	},
	"spec" : {
		"scaleTargetRef" : {
			"kind" : "ReplicationController",
			"name" : "node4-test-v2.0.4.1"
		},
		"minReplicas" : 1,
		"maxReplicas" : 2,
		"targetCPUUtilizationPercentage" : 80
	},
	"status" : {
		"currentReplicas" : 1,
		"desiredReplicas" : 0
	}
}
 */
var logger =undefined;
var httpRequest = require('../common/httpRequest').httpRequest;
var _req = new httpRequest();

 logger = require('../log4js/log4js').logger('kubernetes');

/**
 * the options must include k8s client info,eg host,port,etc
 */
function PodAutoScale() {
}

PodAutoScale.prototype.create = function ( ns,options ) {
    //body parameter required
    if( !options.param ){
        return emptyPromise(null,false,"AutScaler infor not specified") ;
    }
    return createAutoScale( ns , options) ;
}
PodAutoScale.prototype.list = function(ns,options){
    return listAutoScale( ns , options ) ;
}
PodAutoScale.prototype.delete = function(ns,options){
    //autoScalerName required.
    if( !options.autoScalerName ){
        return emptyPromise(null,false,"AutoScalerName not specified") ;
    }
    return deleteAutoScale( ns,options ) ;
}
PodAutoScale.prototype.deleteAll = function(ns,options){
    return deleteAllAutoScale(ns,options) ;
}
PodAutoScale.prototype.find = function(ns,options){
    //autoScalerName required in options
    if( !options.autoScalerName ){
        return emptyPromise(null,false,"AutoScalerName not specified") ;
    }
    return getTheAutoScale( ns,options ) ;
}
PodAutoScale.prototype.replace = function(ns,options){
    if( !options.autoScalerName ){
        return emptyPromise(null,false,"AutoScalerName not specified") ;
    }
    if( !options.param ){
        return emptyPromise(null,false,"AutScaler infor not specified") ;
    }
    return replaceAutoScale(ns,options) ;
}

/**
 * create auto scale
 * Post /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers
 */
function createAutoScale(ns,options){
    if( !ns || !options){
        if(logger){
            logger.error("no namespace specified!") ;
        }
        return ;
    }
    var self = options ;
    var path = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers" ;
    path = path.replace("{namespace}",ns ) ;
    var _url = 'http://' + self.host + ':' + self.port + path;
    //TODO fill the options.param with object like below
    // {
    //     scaleName : param.scaleName,
    //         namespace : param.namespace,
    //     max : param.max,
    //     min : param.min,
    //     refKind : param.refKind,   eg :ReplicationController
    //     refName : param.refName,
    //     cpuPct : param.cpuPct,
    // }
    options["bodyParameter"] =  generateScale(options.param)
    return httpPost(  _url, options ) ;
}

/**
 * list all the auto scale under the namespace
 * GET /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers
 */
function listAutoScale(ns,options){
    var _self = options;
    var path = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers?timeoutSeconds=60" ; //time out in 60 seconds
    path = path.replace("{namespace}",ns ) ;
    var _url = 'http://' + _self.host + ':' + _self.port +path;
    return httpGet( _url, options ) ;
}

/**
 * delete a auto scaler specified by name
 * DELETE /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}
 */
function deleteAutoScale(ns,options){
    var _self = options;
    var autoScalerName = options.autoScalerName ;
    var path = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}?gracePeriodSeconds=60" ; //time out in 60 seconds
    path = path.replace("{namespace}",ns ) ;
    path = path.replace("{name}",autoScalerName );
    var _url = 'http://' + _self.host + ':' + _self.port +path;
    options["bodyParameter"] =  {} ;
    return httpDelete(  _url, options ) ;
}

/**
 * delete all the auto scale under the namespace
 * DELETE /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers
 */
function deleteAllAutoScale(ns,options){
   var _self = options;
   var path = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers?timeoutSeconds=60" ; //time out in 60 seconds
   path = path.replace("{namespace}",ns ) ;
   var _url = 'http://' + _self.host + ':' + _self.port +path;
    options["bodyParameter"] =  {} ;
   return httpDelete(  _url, options ) ;
}

/**
 *  get the information of the auto scale
 *  GET  /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}
 */
function getTheAutoScale( ns,options ){
    var autoScalerName = options.autoScalerName ;
    var _self = options;
    var path = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}" ; //time out in 60 seconds
    path = path.replace("{namespace}",ns ) ;
    path = path.replace("{name}",autoScalerName );
    var _url = 'http://' + _self.host + ':' + _self.port +path;
    return httpGet(  _url, options ) ;
}

/**
 * replace the auto scale with a new one
 * PUT /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}
 */
function replaceAutoScale(ns,options){
    var autoScalerName = options.autoScalerName ;
    var _self = options;
    var path = "/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}" ; //time out in 60 seconds
    path = path.replace("{namespace}",ns ) ;
    path = path.replace("{name}",autoScalerName );
    var _url = 'http://' + _self.host + ':' + _self.port +path;
    // {
    //     scaleName : param.scaleName,
    //     namespace : param.namespace,
    //     max : param.max,
    //     min : param.min,
    //     refKind : param.refKind,
    //     refName : param.refName,
    //     cpuPct : param.cpuPct,
    // }
    options["bodyParameter"] =  generateScale(options.param)
    return httpPut(  _url, options ) ;
}

/**
 * partially update the specified HorizontalPodAutoscaler
 * PATCH /apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}
 */
function partialUpdate(){
    //TODO no need to implement it now
}

function generateScale(param){
    var scaleName = param.scaleName ;
    var namespace = param.namespace ;
    var max = param.max ; //integer
    var min = param.min;  //integer
    var refKind = param.refKind ;
    var refName = param.refName ;
    var cpuPct = param.cpuPct ;  //integer

    return {
        "kind" : "HorizontalPodAutoscaler",
        "apiVersion" : "autoscaling/v1",
        "metadata" : {
            "name" : scaleName,
            "namespace" : namespace
        },
        "spec" : {
            "maxReplicas" : max,
            "minReplicas" : min,
            "scaleTargetRef" : {
                "kind" : refKind,
                "name" : refName
            },
            "targetCPUUtilizationPercentage" : cpuPct
        }
    } ;
}

//repeatedly creating wheels
function httpGet(url,options){
    var _url = url ;
    var _self = options;
    return new Promise(function (resolve, reject) {
        _req._request(_url, 'GET', {}, '', function (data, result, response) {
            if (data !== null) {
                resolve(  JSON.parse(data.data)  );
            } else {
                if(logger){
                    logger.warn("can not get right response "+result.code) ;
                }
                reject(JSON.parse(result));
            }
        });
    });
}

function httpDelete(url,options){
    var _url = url ;
    var _self = options;
    var bodyParameter = options.bodyParameter||{} ;

    return new Promise(function (resolve, reject) {
        //var _url = 'http://' + self.host + ':' + self.port + '/apis/batch/v1/namespaces/default/jobs/' + job_id;
        _req._request(_url, 'DELETE', {"Content-Type": "application/json"}, JSON.stringify(bodyParameter), function (data, result, response) {
            if (data !== null) {
                resolve(  JSON.parse(data.data)  );
            }else {
                if(logger){
                    logger.warn(_url+"can not get right response "+result) ;
                }
                reject(JSON.parse(result));
            }
        });
    });
}

function httpPost(url,options){
    var _url = url ;
    var _self = options;
    var bodyParameter = options.bodyParameter ;

    return new Promise(function (resolve, reject) {
        // var _url = 'http://' + self.host + ':' + self.port + path;
        _req._request(_url, 'POST', {"Content-Type": "application/json"}, JSON.stringify(bodyParameter), function (data, result, response) {
            if (data !== null) {
                resolve(  JSON.parse(data.data)  );
            } else {
                if(logger){
                    logger.warn("can not get right response "+result) ;
                }
                reject(JSON.parse(result)) ;
            }
        });
    });
}

function httpPut(url,options){
    var _url = url ;
    var _self = options;
    var bodyParameter = options.bodyParameter ;
    return new Promise(function (resolve, reject) {
        _req._request(_url, 'PUT', {"Content-Type": "application/json"}, JSON.stringify(bodyParameter) , function (data, result, response) {
            if (data !== null ){
                resolve( JSON.parse(data.data) ) ;
            } else {
                if(logger){
                    logger.warn("can not get right response "+result) ;
                }
                reject(JSON.parse(result)) ;
            }
        });
    });
}

function emptyPromise(data,isSuccess,message){
    return new Promise(function (resolve, reject) {
            if( isSuccess ){
                resolve(data);
            } else {
                if (logger) {
                    logger.error("Empty promise return failed," + message);
                }
                reject( message );
            }
    });
}

module.exports = PodAutoScale